package com.marmot.cloud.framework.core.response;

import com.marmot.cloud.framework.core.constant.ResultCode;
import com.marmot.cloud.framework.core.constant.C;
import cn.hutool.json.JSONUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.servlet.ServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.io.PrintWriter;
import java.io.Serializable;

@Slf4j
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "统一返回信息模型")
public class R<T> implements Serializable {

    @Schema(description = "返回码", required = true)
    private Integer code;
    @Schema(description = "返回消息", required = true)
    private String msg;
    @Schema(description = "返回数据", required = true)
    private T data;

    public static <T> R<T> success() {
        return success(null);
    }

    public static <T> R<T> success(Integer code, String msg) {
        return new R(code, msg, null);
    }

    public static <T> R success(String msg, T data) {
        return new R(C.SUCCESS.getResultCode(), msg, data);
    }

    /**
     * 返回成功信息
     **/
    public static <T> R<T> success(T data) {
        return new R(C.SUCCESS.getResultCode(), C.SUCCESS.getResultMsg(), data);
    }

    /**
     * 返回错误信息
     **/
    public static <T> R<T> error(ResultCode errorInfo) {
        return new R(errorInfo.getResultCode(), errorInfo.getResultMsg(), null);
    }

    /**
     * 返回错误信息
     */
    public static <T> R<T> error(Integer code, String msg) {
        return new R(code, msg, null);
    }

    /**
     * 返回错误信息
     */
    public static <T> R<T> error(String msg) {
        return new R(C.ERROR.getResultCode(), msg, null);
    }

    /**
     * 返回错误信息
     */
    public static <T> R<T> error() {
        return new R(C.ERROR.getResultCode(), C.ERROR.getResultMsg(), null);
    }

    public static <T> R<T> failure() {
        return new R(C.FAILURE.getResultCode(), C.FAILURE.getResultMsg(), null);
    }

    public static <T> R<T> failure(String msg) {
        return new R(C.FAILURE.getResultCode(), msg, null);
    }

    /**
     * 返回失败信息
     **/
    public static <T> R<T> failure(ResultCode errorInfo) {
        return new R(errorInfo.getResultCode(), errorInfo.getResultMsg(), null);
    }

    public static <T> void success(ServletResponse response, T data) {
        success(response, C.SUCCESS.getResultMsg(), data);
    }

    public static <T> void success(ServletResponse response, String msg, T data) {
        PrintWriter out = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            out = response.getWriter();
            out.println(JSONUtil.toJsonStr(new R(C.SUCCESS.getResultCode(), msg, data)));
        } catch (Exception e) {
            log.error("【JSON输出异常】" + e);
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }

    public static <T> void error(ServletResponse response, T data) {
        error(response, C.ERROR.getResultMsg(), data);
    }

    public static <T> void error(ServletResponse response, String msg, T data) {
        PrintWriter out = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            out = response.getWriter();
            out.println(JSONUtil.toJsonStr(new R(C.ERROR.getResultCode(), msg, data)));
        } catch (Exception e) {
            log.error("【JSON输出异常】" + e);
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }

    public static <T> R<T> failure(Integer code, String msg) {
        return new R(code, msg, null);
    }

    public static <T> void failure(ServletResponse response, T data) {
        failure(response, C.FAILURE.getResultMsg(), data);
    }

    public static <T> void failure(ServletResponse response, String msg, T data) {
        PrintWriter out = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            out = response.getWriter();
            out.println(JSONUtil.toJsonStr(new R(C.FAILURE.getResultCode(), msg, data)));
        } catch (Exception e) {
            log.error("【JSON输出异常】" + e);
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }

}
